package com.smedi.ismedi.personnel.core.domain.service.impl;

import com.smedi.ismedi.personnel.core.domain.aggregatemodel.Person;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.model.SimplePerson;
import com.smedi.ismedi.personnel.core.domain.repository.PersonRepository;
import com.smedi.ismedi.personnel.core.domain.service.PersonDomainService;
import com.smedi.ismedi.personnel.core.infrastructure.constant.CustomError;
import com.smedi.ismedi.personnel.core.infrastructure.enumerate.PersonStatusEnum;
import com.smedi.ismedi.personnel.core.infrastructure.enumerate.PersonTypeEnum;
import com.smedi.ismedi.personnel.core.port.adapter.service.UserManagementRemoteApiService;
import com.smedi.ismedi.web.starter.exception.LogicException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.regex.Pattern;

/**
 * @Author: xulinjun
 * @Date: 2021-6-8 13:58
 */
@Slf4j
@Service
@AllArgsConstructor
public class PersonDomainServiceImpl implements PersonDomainService {
    private final PersonRepository personRepository;

    private final UserManagementRemoteApiService userManagementRemoteApiService;

    @Override
    public Person saveInternalPerson(Person person) {
        return savePerson(person, true);
    }

    @Override
    public Person saveExternalPerson(Person person) {
        return savePerson(person, false);
    }

    @Override
    public void createSimplePerson(SimplePerson simplePerson) {
        personRepository.saveSimplePerson(simplePerson);
    }

    @Override
    public void editSimplePerson(SimplePerson simplePerson) {
        personRepository.saveSimplePerson(simplePerson);
    }

    // 校验员工号是否重复
    @Override
    public Boolean duplicateEmployeeNum(String employeeNum, Long personId) {
        return personRepository.selectEmployeeNumCount(employeeNum, personId,false) > 0;
    }

    // 校验身份证号是否重复
    @Override
    public Boolean duplicateIdCard(String idCard, Long personId) {
        return personRepository.selectIdCardCount(idCard, personId,false) > 0;
    }

    // 校验手机号是否重复
    @Override
    public Boolean duplicateMobile(String mobile, Long personId) {
        return personRepository.selectMobileCount(mobile, personId,false) > 0;
    }

    @Override
    public Boolean validateEmailFormat(String email) {
        return Pattern.matches("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+", email);
    }

    @Override
    public Boolean validateIdCardFormat(String idCard) {
        return Pattern.matches("^(\\d{18,18}|\\d{15,15}|(\\d{17,17}[x|X]))$", idCard);
    }

    @Override
    public Boolean validateMobileFormat(String mobile) {
        return Pattern.matches("^((1)\\d{10})$", mobile);
    }

    @Override
    public Person queryByIdCard(String idCard) {
        return personRepository.selectByIdCard(idCard,false);
    }

    @Override
    public Boolean isInternal(Long personId) {
        Person person = personRepository.selectByPersonId(personId,false);
        if (person != null) {
            return PersonTypeEnum.COMPANY_MEMBER.getValue().equals(person.getPersonType());
        } else {
            return false;
        }
    }

    @Override
    public Boolean isExternal(Long personId) {
        Person person = personRepository.selectByPersonId(personId,false);
        if (person != null) {
            return PersonTypeEnum.PROJECT_EXTERNAL_MEMBER.getValue().equals(person.getPersonType()) || PersonTypeEnum.PROJECT_MEMBER.getValue().equals(person.getPersonType());
        } else {
            return false;
        }
    }

    @Override
    public Boolean isAvailable(Long personId) {
        Person person = personRepository.selectByPersonId(personId,false);
        return person != null;
    }

    @Override
    public void editPersonStatus(Long personId, boolean enable) {
        Person basic = personRepository.selectByPersonId(personId,false);
        if (basic == null) {
            throw LogicException.raise(CustomError.PERSON_NOT_EXIST);
        } else {
            String targetStatus = enable ? PersonStatusEnum.ENABLE.getValue() : PersonStatusEnum.DISABLE.getValue();
            if (basic.getStatus().equals(targetStatus)) {
                throw LogicException.raise(CustomError.STATUS_CAN_NOT_THE_SAME);
            } else {
                basic.setStatus(targetStatus);
                personRepository.doUpdate(basic);
            }
        }

        // TODO 调用消息组件修改人员类型
        if (enable) {
            userManagementRemoteApiService.enableAccount(personId);
        } else {
            userManagementRemoteApiService.disableAccount(personId);
        }
    }

    @Override
    public void deleteByPersonId(Long personId) {
        Person basic = personRepository.selectByPersonId(personId,false);
        if (basic == null) {
            throw LogicException.raise(CustomError.PERSON_NOT_EXIST);
        } else {
            personRepository.doDeleteByPersonId(personId);
        }
    }

    /**
     * 校验身份证是否填写、格式
     *
     * @param idCard
     */
    private void validateIdCard(String idCard) {
        if (StringUtils.isEmpty(idCard)) {
            throw LogicException.raise(CustomError.ID_CARD_EMPTY);
        } else {
            // 判断身份证格式
            if (!validateIdCardFormat(idCard)) {
                throw LogicException.raise(CustomError.ID_CARD_FORMAT_ERROR);
            }
        }
    }

    // 保存信息
    private Person savePerson(Person data, boolean internal) {
        Person basic;
        if (data.getPersonId() != null) {
            basic = personRepository.selectByPersonId(data.getPersonId(),false);
            if (basic == null) {
                throw LogicException.raise(CustomError.PERSON_NOT_EXIST);
            }

            // 如果当前是更新情况，并且身份证字段是动过的，则需要保存
            if (data.isModifyIdCard()) {
                basic.setIdCard(data.getIdCard().toUpperCase());
                // 身份证校验
                validateIdCard(basic.getIdCard());
            }
        } else {
            basic = new Person()
                    .setStatus(PersonStatusEnum.ENABLE.getValue())
                    .setIdCard(data.getIdCard().toUpperCase());
            // 身份证校验
            validateIdCard(basic.getIdCard());
        }

        // 为了保障数据查询速度和规范，身份证需大写处理入库。
        // 用户状态新增的时候默认为开启，更新时不操作
        basic.setEmail(data.getEmail())
                .setGender(data.getGender())
                .setEmployeeNum(data.getEmployeeNum())
                .setPersonType(data.getPersonType())
                .setLastName(data.getLastName())
                .setOfficeTelephone(data.getOfficeTelephone())
                .setMobile(data.getMobile())
                .setPersonOrder(data.getPersonOrder())
                .setInternal(internal); // 内部外部人员标识

        // 企业员工校验员工号是否重复
        if (internal) {
            if (duplicateEmployeeNum(basic.getEmployeeNum(), basic.getPersonId())) {
                throw LogicException.raise(CustomError.EMPLOYEE_NUM_DUPLICATE);
            }
        }
        // 身份证号是否重复校验
        if (duplicateIdCard(basic.getIdCard(), basic.getPersonId())) {
            throw LogicException.raise(CustomError.ID_CARD_DUPLICATE);
        }
        // 手机号是否重复校验
        if (duplicateMobile(basic.getMobile(), basic.getPersonId())) {
            throw LogicException.raise(CustomError.MOBILE_DUPLICATE);
        }

        // 保存数据
        Person domain = (data.getPersonId() == null) ? personRepository.doInsert(basic) : personRepository.doUpdate(basic);

        return domain;
    }

    @Override
    public void createAccount(Person person) {
        String userName = userManagementRemoteApiService.generateAccount(person.getPersonId(), person.getMobile(), person.getIdCard(), person.getLastName());
        Person basic = personRepository.selectByPersonId(person.getPersonId(),false);
        if (basic != null) {
            basic.setUserName(userName);
            personRepository.doUpdate(basic);
        } else {
            throw LogicException.raise(CustomError.PERSON_NOT_EXIST, null, "创建用户阶段！");
        }
    }

    @Override
    public boolean isMobileChanged(Long personId, String newMobile) {
        if (personId != null) {
            Person basic = personRepository.selectByPersonId(personId,false);
            if (basic != null) {
                if (basic.getMobile() != null) {
                    return !basic.getMobile().equals(newMobile);
                } else {
                    return !StringUtils.isEmpty(newMobile);
                }
            } else {
                throw LogicException.raise(CustomError.PERSON_NOT_EXIST, null, "创建用户阶段！");
            }
        } else {
            return false;
        }
    }
}
